<?php
/**
 * bs多规格sku商城系统
 * ============================================================================
 * 版权所有 2024-2099 wltx666.com，并保留所有权利。
 * 网站地址: https://wltx666.com
 * ============================================================================
 * Author: 草上飞
 * Email: wltx@alipay168.cn
 * QQ: 2719875001
 * Date: 2025/1/10
 * 描述:
 */

namespace app\result\admin;

use app\model\admin\AdminMenu;
use app\result\BaseResult;
use app\service\CurdService;
use think\facade\Db;

class CurdResult extends BaseResult
{
    public function table_info($args): array
    {
        $table = $args['table_name'] ?? "";
        if (!$table) {
            return self::error_return('请传入表名');
        }
        //先查询表是否存在
        $table_exist = Db::query("SHOW TABLES LIKE '{$table}'");
        if (!$table_exist) {
            return self::error_return('表不存在');
        }

        $table_info = Db::query("SHOW FULL COLUMNS FROM `{$table}`");
        return self::success_return('获取成功', $table_info);
    }

    // 将字符串按下划线分割成数组，将每个单词的首字母大写，再合并成字符串
    private function toCamelCase($str)
    {
        // 将字符串按下划线分割成数组
        $arr = explode('_', $str);
        // 遍历数组，将每个单词的首字母大写
        $arr = array_map('ucfirst', $arr);
        // 将数组合并成字符串
        return implode('', $arr);
    }


    public function save_data($args): array
    {
        //bs_log($args, 'save_data', 'curd.log');
        $tableName = $args['tableName'] ?? "";
        $admin_apis = $args['admin_apis'] ?? [];//后台接口
        $apis = $args['apis'] ?? [];//前端接口
        $menu_name = $args['menu_name'] ?? "";
        $isCreatePermission = !empty($args['isCreatePermission']);
        if (!$tableName) {
            return self::error_return('请传入数据表名');
        }
        if ($isCreatePermission) {
            if (!$menu_name) {
                return self::error_return('请传入菜单名称');
            }
            if (!$admin_apis) {
                return self::error_return('设置权限后台接口配置至少选一项');
            }

        }
        $columns = $args['columns'] ?? [];
        if (!$columns) {
            return self::error_return('请传入字段');
        }
        $table_info = Db::query("SHOW FULL COLUMNS FROM `{$tableName}`");
        if (!$table_info) {
            return self::error_return('表不存在');
        }
        //查询自增ID
        $autoIncrementId = 'id';
        foreach ($table_info as $item) {
            if (strtolower($item['Extra']) == 'auto_increment') {
                $autoIncrementId = $item['Field'];
            }
        }
        //设置自增ID字段
        CurdService::set_auto_increment_field($autoIncrementId);

        $searchFields = [];

        $tableFields = [];
        foreach ($columns as $item) {
            if ($item['isSearchable']) {
                $s = [
                    'name' => $item['Field'],
                    'label' => $item['ShowListDisplayName'],
                    'type' => $item['componentType'],
                    'placeholder' => $item['searchDisplayName']
                ];
                if ($item['componentType'] == 'select') {
                    $s['options'] = $item['options'];
                }
                $searchFields[] = $s;
            }
            if ($item['isShowList']) {
                $tmp = [
                    'prop' => $item['Field'],
                    'type' => 'text',
                    'label' => $item['ShowListDisplayName'],
                    'minWidth' => 120,
                    'align' => 'center',
                ];
                if ($item['componentType'] == 'select') {
                    $tmp['type'] = 'tags';
                    $tmp['tags'] = [];
                    foreach ($item['options'] as $option) {
                        $tmp['tags'][$option['value']] = [
                            'label' => $option['label'],
                            'color' => '',
                            'type' => 'success',
                        ];
                    }
                } elseif ($item['componentType'] == 'image') {
                    $tmp['type'] = 'image';
                }
                $tableFields[] = $tmp;
            }
        }

        $prefix = config('database.prefix');
        if ($prefix) {
            $tableName = substr($tableName, strlen($prefix));
        }
        $className = $this->toCamelCase($tableName);

        $resultPath = app()->getRootPath() . '/app/result/auto/' . $className . 'Result.php';
        if (file_exists($resultPath)) {
            //return self::error_return('类已存在');
        }
        $tplResult = CurdService::tpl_result([
            'className' => $className . 'Result',
            'modelName' => $className,
            'tableFields' => $tableFields,
            'searchFields' => $searchFields,
            'admin_apis' => $admin_apis,
            'apis' => $apis,
        ]);
        //如果目录不存在，则创建
        //获取路径
        $path = dirname($resultPath);
        if (!is_dir($path)) {
            mkdir($path, 0777, true);
        }
        file_put_contents($resultPath, $tplResult);
        $tplModel = CurdService::tpl_model([
            'modelName' => $className,
        ]);
        $modelPath = app()->getRootPath() . '/app/model/auto/' . $className . '.php';
        if (file_exists($modelPath)) {
            //return self::error_return('模型已存在');
        }
        if (!is_dir(dirname($modelPath))) {
            mkdir(dirname($modelPath), 0777, true);
        }
        file_put_contents($modelPath, $tplModel);
        //是否需要后端控制器
        if (!empty($admin_apis)) {
            $controllerPath = app()->getAppPath() . '/controller/auto/' . $className . '.php';
            $tplController = CurdService::tpl_admin_controller([
                'className' => $className,
                'resultName' => $className . 'Result',
                'admin_apis' => $admin_apis,
                'apis' => $apis,
            ]);
            if (!is_dir(dirname($controllerPath))) {
                mkdir(dirname($controllerPath), 0777, true);
            }
            file_put_contents($controllerPath, $tplController);
            $routePath = app()->getAppPath() . '/route/admin_' . strtolower($tableName) . '.php';
            $tplRoute = CurdService::tpl_admin_route([
                'group' => strtolower($tableName),
                'className' => $className,
                'admin_apis' => $admin_apis,
                'apis' => $apis,
            ]);
            if (!is_dir(dirname($routePath))) {
                mkdir(dirname($routePath), 0777, true);
            }

            file_put_contents($routePath, $tplRoute);

            //创建权限菜单
            if ($isCreatePermission) {
                $this->create_auth_menu($menu_name, $admin_apis, $args);
            }

            //生成管理后台前端文件
            $this->make_admin_front_file([
                'tableName' => $tableName,
                'admin_apis' => $admin_apis,
                'auto_increment_id' => $autoIncrementId,
            ]);
        }
        //是否需要前端控制器
        if (!empty($apis)) {
            //前端控制器
            $controllerPath = app()->getRootPath() . '/app/api/controller/auto/' . $className . '.php';
            $tplController = CurdService::tpl_front_controller([
                'className' => $className,
                'resultName' => $className . 'Result',
                'apis' => $apis,
            ]);
            if (!is_dir(dirname($controllerPath))) {
                mkdir(dirname($controllerPath), 0777, true);
            }
            file_put_contents($controllerPath, $tplController);
            //前端路由
            $routePath = app()->getRootPath() . '/app/api/route/api_' . strtolower($tableName) . '.php';
            $tplRoute = CurdService::tpl_front_route([
                'group' => strtolower($tableName),
                'className' => $className,
                'apis' => $apis,
            ]);
            if (!is_dir(dirname($routePath))) {
                mkdir(dirname($routePath), 0777, true);
            }
            file_put_contents($routePath, $tplRoute);

            //生成app文件
            $this->make_app_file([
                'tableName' => $tableName,
                'apis' => $apis,
                'auto_increment_id' => $autoIncrementId,
            ]);
        }

        return self::success_return('生成成功');
    }

    //生成app文件
    private function make_app_file($args)
    {
        $tableName = $args['tableName'];
        $apis = $args['apis'];
        $toDir = app()->getRuntimePath() . '/temp/curd/app/';
        if (!is_dir($toDir)) {
            mkdir($toDir, 0777, true);
        }
        $tpl_app_js = file_get_contents(__DIR__ . '/tpl/app_api_js.tpl');
        $tpl_app_js = str_replace('$bs_table_name', $tableName, $tpl_app_js);
        if (in_array('list', $apis)) {
            $tpl_app_js .= <<<doc

export const list = (params) => {
    return Vue.prototype.\$u.get(basePath + '/list', params);
};
doc;;
        }
        if (in_array('detail', $apis)) {
            $tpl_app_js .= <<<doc

export const detail = (params) => {
    return Vue.prototype.\$u.get(basePath + '/detail', params);
};
doc;
        }
        if (in_array('action', $apis)) {
            $tpl_app_js .= <<<doc

export const action = (params) => {
    return Vue.prototype.\$u.post(basePath + '/action', params);
};
doc;
        }
        if (in_array('remove', $apis)) {
            $tpl_app_js .= <<<doc

export const remove = (params) => {
    return Vue.prototype.\$u.delete(basePath + '/remove', params);
};
doc;
        }
        if (in_array('setDefault', $apis)) {
            $tpl_app_js .= <<<doc

export const setDefault = (params) => {
    return Vue.prototype.\$u.put(basePath + '/setDefault', params);
};
doc;
        }
        if (in_array('list_options', $apis)) {
            $tpl_app_js .= <<<doc

export const list_options = (params) => {
    return Vue.prototype.\$u.get(basePath + '/list_options', params);
};
doc;
        }

        file_put_contents($toDir . $tableName . '_api.js', $tpl_app_js);

    }

    //生成管理后台前端文件
    private function make_admin_front_file($args)
    {
        $tableName = $args['tableName'];
        $admin_apis = $args['admin_apis'];
        $auto_increment_id = $args['auto_increment_id'];
        $bsTableFromName = $this->toCamelCase($tableName) . 'Form';//表单名称，前端路由需要
        $prefix = config('database.prefix');
        if ($prefix) {
            $tableName = substr($tableName, strlen($prefix));
        }
        $tpl_admin_api_js = file_get_contents(__DIR__ . '/tpl/admin_api_js.tpl');
        $tpl_admin_list_vue = file_get_contents(__DIR__ . '/tpl/admin_list.tpl');
        $toDirAdmin = app()->getRuntimePath() . '/temp/curd/admin/';
        if (!is_dir($toDirAdmin)) {
            mkdir($toDirAdmin, 0777, true);
        }
        $tpl_admin_list_vue = str_replace('$bs_table_name', $tableName, $tpl_admin_list_vue);
        $tpl_admin_list_vue = str_replace('$bs_auto_id', $auto_increment_id, $tpl_admin_list_vue);
        $tpl_admin_list_vue = str_replace('$bsTableFromName', $bsTableFromName, $tpl_admin_list_vue);

        if (in_array('save_data', $admin_apis)) {
            $tpl_admin_list_vue = str_replace('<!--$bs_add_btn-->', <<<doc
<el-button type="success" size="mini" icon="el-icon-plus" @click="\$router.push({path:'$bsTableFromName'})">新增
        </el-button>
doc
                , $tpl_admin_list_vue);
            $tpl_admin_list_vue = str_replace('<!--$bs_edit_btn-->', <<<doc
<el-button size="mini" type="primary" title="修改" icon="el-icon-edit" circle @click="\$router.push({path:'$bsTableFromName',query:{id:row.$auto_increment_id}})"/>
doc
                , $tpl_admin_list_vue);
        }
        if (in_array('del_data', $admin_apis)) {
            $tpl_admin_list_vue = str_replace('<!--$bs_delete_btn-->', <<<doc
<el-button type="danger" size="mini" icon="el-icon-delete" circle @click="del(row.$auto_increment_id)"></el-button>
doc, $tpl_admin_list_vue);
            $tpl_admin_list_vue = str_replace('/*$bs_js_delete_method*/', <<<doc
del(id) {
      this.\$confirm('此操作将删除此数据, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        api.del({ id: id }).then(res => {
          this.\$message({
            type: 'success',
            message: res.msg
          })
          this.fetchData()
        })
      }).catch(() => {

      })
    },

doc, $tpl_admin_list_vue);

        }


        //生成前端列表页
        file_put_contents($toDirAdmin . $tableName . '_list.vue', $tpl_admin_list_vue);

        $tpl_admin_api_js = str_replace('$bs_table_name', $tableName, $tpl_admin_api_js);
        $bs_replace_body = '';
        if ($admin_apis) {
            foreach ($admin_apis as $admin_api) {
                if ($admin_api == 'list') {
                    $bs_replace_body .= <<<doc
    getList(params) {
        return request({
            url: this.path + '/list',
            method: 'get',
            params
        })
    },
doc;

                } elseif ($admin_api == 'get') {
                    $bs_replace_body .= <<<doc

    info(params) {
        return request({
            url: this.path + '/get',
            method: 'get',
            params
        })
    },
doc;
                } elseif ($admin_api == 'save_data') {
                    $bs_replace_body .= <<<doc

    create(data) {
        return request({
            url: this.path + '/save',
            method: 'post',
            data
        })
    },    
    update(data) {
        return request({
            url: this.path + '/save',
            method: 'put',
            data
        })
    },
doc;
                } elseif ($admin_api == 'del_data') {
                    $bs_replace_body .= <<<doc

    del(data) {
        return request({
            url: this.path + '/delete',
            method: 'delete',
            data
        })
    },
doc;
                } elseif ($admin_api == 'list_options') {
                    $bs_replace_body .= <<<doc

    list_options(params) {
        return request({
            url: this.path + '/list_options',
            method: 'get',
            params
        })
    },
doc;
                } elseif ($admin_api == 'status') {
                    $bs_replace_body .= <<<doc

    status(data) {
        return request({
            url: this.path + '/status',
            method: 'put',
            data
        })
    },

doc;
                }
            }
            $tpl_admin_api_js = str_replace('$bs_replace_body', $bs_replace_body, $tpl_admin_api_js);
        }


        //生成管理后台前端api
        file_put_contents($toDirAdmin . $tableName . '_api.js', $tpl_admin_api_js);


    }

    private function create_auth_menu($menu_name, $admin_apis, $args)
    {
        //核心的菜单不需要就跳过
        if (!in_array('list', $admin_apis) && !in_array('get', $admin_apis)) {
            return true;
        }
        $tableName = $args['tableName'];
        $prefix = config('database.prefix');
        if ($prefix) {
            $tableName = substr($tableName, strlen($prefix));
        }
        $parentData = [
            'type' => 0,//类型：0=菜单-页面；1=功能-权限
            'parent_id' => 0,
            'path' => "/admin/$tableName/list",
            'name' => $menu_name,
            'component' => "@/views/$tableName/list",
            'redirect' => '',
            'title' => $menu_name,
            'icon' => 'el-icon-menu',
            'hidden' => 0,
        ];
        $result = new MenusResult();
        $res = $result->quick_add($parentData);
        if ($res['code'] <> 0) {
            return self::error_return('创建菜单失败');
        }
        $matchRoute = [
            'list' => ['name' => '列表', 'route' => 'list'],
            'get' => ['name' => '详情', 'route' => 'get'],
            'save_data' => ['name' => '增改', 'route' => 'save'],
            'del_data' => ['name' => '删除', 'route' => 'delete'],
            'list_options' => ['name' => '下拉选项', 'route' => 'list_options'],
            'status' => ['name' => '快速修改状态', 'route' => 'status'],
        ];
        $menu_id = $res['data']['id'];
        $baseData = [];
        foreach ($admin_apis as $api) {
            if ($api == 'list') {
                continue;
            }
            $baseData[] = [
                'type' => 1,//类型：0=菜单-页面；1=功能-权限
                'parent_id' => $menu_id,
                'path' => "/admin/$tableName/" . $matchRoute[$api]['route'],
                'name' => $matchRoute[$api]['name'],
                'component' => $parentData['component'],
                'redirect' => '',
                'title' => $matchRoute[$api]['name'],
                'icon' => 'el-icon-menu',
                'hidden' => 1,
            ];
        }
        if ($baseData) {
            (new AdminMenu())->allowField(['parent_id', 'path', 'name', 'component', 'redirect', 'title', 'icon', 'hidden', 'sort', 'type'])->saveAll($baseData);
        }
        return true;
    }

}
